<?php

namespace app\common\service;

class LetterDraw
{
    public static $page = 1;
    public static $text_indent = 2;
    public static $padding_left = 200;
    public static $width = 1700;
    public static $font_size = 60;
    public static $color = [255, 255, 255];
    public static $background = '';
    public static $font_family = '/uploads/20250113/26875b76b6ab093668e3aff79f33b485.ttf';
    public static $is_write =   true;
    public static $symbol_br = true;//符号强行放在一;
    public static $line_height = 110;

    public static $tit_param;
    public static $param;
    public static $sign_param;
    public static $date_param;


    public function __construct($tit_param,$sign_param,$param,$date_param,$is_write=true){
        self::$param = $param;
        self::$tit_param = $tit_param;
        self::$sign_param = $sign_param;
        self::$date_param = $date_param;
        self::$is_write = $is_write;
    }
    public function draw()
    {

//        $tit_param = [
//            'content' => '亲爱的王艺璇:',
//            'padding_top' => 200,
//            'maxline' => 1,
//            'text_align' => 'left',
//        ];
//
//        $sign_param = [
//            'content' => '想找妹子，想找女人',
//            'padding_top' => 2800,
//            'maxline' => 1,
//            'text_align' => 'right',
//        ];
//
//        $param = [
//            'content' => '先帝创业未半而中道崩殂，今天下三分，益州疲弊，此诚危急存亡之秋也。然侍卫之臣不懈于内，忠志之士忘身于外者，盖追先帝之殊遇，欲报之于陛下也。诚宜开张圣听，以光先帝遗德，恢弘志士之气，不宜妄自菲薄，引喻失义，以塞忠谏之路也。^ 宫中府中，俱为一体，陟罚臧否，不宜异同。若有作奸犯科及为忠善者，宜付有司论其刑赏，以昭陛下平明之理，不宜偏私，使内外异法也。^ 侍中、侍郎郭攸之、费祎、董允等，此皆良实，志虑忠纯，是以先帝简拔以遗陛下。愚以为宫中之事，事无大小，悉以咨之，然后施行，必得裨补阙漏，有所广益。^ 将军向宠，性行淑均，晓畅军事，试用之于昔日，先帝称之曰能，是以众议举宠为督。愚以为营中之事，悉以咨之，必能使行阵和睦，优劣得所。^ 亲贤臣，远小人，此先汉所以兴隆也；亲小人，远贤臣，此后汉所以倾颓也。先帝在时，每与臣论此事，未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军，此悉贞良死节之臣，愿陛下亲之信之，则汉室之隆，可计日而待也。^ 臣本布衣，躬耕于南阳，苟全性命于乱世，不求闻达于诸侯。先帝不以臣卑鄙，猥自枉屈，三顾臣于草庐之中，咨臣以当世之事，由是感激，遂许先帝以驱驰。后值倾覆，受任于败军之际，奉命于危难之间，尔来二十有一年矣。^ 先帝知臣谨慎，故临崩寄臣以大事也。受命以来，夙夜忧叹，恐托付不效，以伤先帝之明，故五月渡泸，深入不毛。今南方已定，兵甲已足，当奖率三军，北定中原，庶竭驽钝，攘除奸凶，兴复汉室，还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益，进尽忠言，则攸之、祎、允之任也。^ 愿陛下托臣以讨贼兴复之效，不效，则治臣之罪，以告先帝之灵。若无兴德之言，则责攸之、祎、允等之慢，以彰其咎；陛下亦宜自谋，以咨诹善道，察纳雅言，深追先帝遗诏，臣不胜受恩感激。^ 今当远离，临表涕零，不知所言。',
//            'padding_top' => 400,
//            'maxline' => 20,
//            'text_align' => 'left',
//        ];

        $orignal_param = $main_param = [
            'page' => self::$page,
            'text_indent' => self::$text_indent,
            'padding_left' => self::$padding_left,
            'width' => self::$width,
            'font_size' => self::$font_size,
            'color' => self::$color,
            'background' => self::$background,
            'font_family' => self::$font_family,
            'is_write' => self::$is_write,
            'symbol_br' => self::$symbol_br,
            'line_height' => self::$line_height,
        ];

        // 加载背景图片
        $background = imagecreatefromjpeg($main_param['background']); // 根据图片格式使用不同的函数，如 imagecreatefrompng(), imagecreatefromgif() 等

        // 获取背景图片的宽高
        $width = imagesx($background);
        $height = imagesy($background);

        // 在背景上创建一个新的图像资源（可以绘制文字等）===
        $image = imagecreatetruecolor($width, $height);

        // 将背景图像复制到新图像上
        imagecopy($image, $background, 0, 0, 0, 0, $width, $height);


        if($main_param['page']==1){
            //标题
            $this->div_make(self::$tit_param['content'],$main_param,$image,$main_param['is_write'],0,self::$tit_param['padding_top'],0,self::$tit_param['maxline'],self::$tit_param['text_align']);
        }

        $explode_str = explode('^', self::$param['content']);

        $cur_page = 1;
        $padding_top = self::$param['padding_top'];
        $text_indent = $main_param['text_indent'];
        $already_line = 0;

        //概况：这里不管怎么样都会把所有页遍历过去，但是只输出当前页的内容
        for($i = 0; $i < count($explode_str); $i++) {
            //这一段需要写的内容
            $str = $explode_str[$i];
            //只写想写的那页
            if($cur_page == $main_param['page'] && $main_param['is_write']) {
                $is_write = true;
            }else{
                $is_write = false;
            }
            $result = $this->div_make($str,$main_param,$image,$is_write,$text_indent,$padding_top,$already_line,self::$param['maxline'],self::$param['text_align']);
            //考虑到1.1这种情况就需要把默认的首行缩进重置回来
            $text_indent = $main_param['text_indent'];
            //如果一行没有写完就把剩下的留到下一页
            if($result['residueStr']){
                //新开一页，但是这段没写完的部分要留到下一页写
                $explode_str[$i] = $result['residueStr'];
                $i--;
                //1.1这种时候首行就不要缩进了
                $text_indent = 0;
                //重新开一页很多东西要重置
                $cur_page ++;
                $padding_top = self::$param['padding_top'];
                $already_line = 0;

            }else{
                $padding_top = $result['div_height'];//累计每个段落距离顶部的高度
                $already_line = $result['wrote_rows'];//累计已写行数
            }

        }

        //这里就遍历到最后一页了
        if($cur_page == $main_param['page']){
            //属名
            $this->div_make(self::$sign_param['content'],$main_param,$image,$main_param['is_write'],0,self::$sign_param['padding_top'],0,self::$sign_param['maxline'],self::$sign_param['text_align']);
            //日期
            $this->div_make(self::$date_param['content'],$main_param,$image,$main_param['is_write'],0,self::$date_param['padding_top'],0,self::$date_param['maxline'],self::$date_param['text_align']);
        }


        if(!$main_param['is_write']){
            //不写，直接输出总页数
            return $cur_page;
        }else{
            // 设置输出为图片类型
            header('Content-Type: image/png');
            // 输出图像为 PNG 格式
            imagepng($image);

            // 清理内存
            imagedestroy($image);
            imagedestroy($background);

        }
    }


//<div style='padding_top:xpx;background:xx.png;'>
    //<div style='padding_left:xpx;line_height:xpx;font_size:xpx;text_indent:xem;font_family:x;width:xpx;text_align:x;'>
    //    <p>我们把这个</p>
    //    br
    //    <p>函数这样看</p>
    //    br
    //    <p>就方便理解</p>
    //    br
    //    <p>了</p>
    //</div>
    //<div>
    //    <p>一次调用这</p>
    //    br
    //    <p>个函数，相</p>
    //    br
    //    <p>当于一个这</p>
    //    br
    //    <p>样的div</p>
    //</div>
//</div>

    /* 在gd里面花可以自动换行的div，看上面*看上面*看上面
         * @param $container 画板
         * @return 数组 tp:本次写入行数  wrote_rows:一共写入行数  residueStr:截取未写完的字符串 height:最后一行据顶部的高度
         */
    public static function div_make($content,$data,$container,$is_write,$text_indent,$padding_top,$already_line,$maxline,$text_align){
        $div_height = $padding_top;//文字在整个图片距离顶端的位置，也就是y轴的像素距离

        $font_size = $data["font_size"];//文字的大小
//    $width = $data["width"];//设置文字换行的宽带，也就是多宽的距离，自动换行
//    $padding_left = $data["padding_left"];//文字在整个图片距离左边的位置，也就是X轴的像素距离
        $line_height = $data["line_height"];// 这个是行高
        $rows_total = $already_line;
        $p = "";
        $br = false; //换号的标示,已换行true ,未换行false;
        $font_file =$data['font_family'];//字体文件，在我的同级目录的Fonts文件夹下面
        $rows_count = 0;
        $font_color = imagecolorallocate($container, $data["color"][0], $data["color"][1], $data["color"][2]);

        $cn_width = imagettfbbox($font_size, 0, $font_file, '测');//用来测量每个字的大小
        $cn_width = $cn_width[2] - $cn_width[0];

        $en_width = imagettfbbox($font_size, 0, $font_file, 'z');//用来测量每个字的大小
        $en_width = $en_width[2] - $en_width[0];

        $emojis = [];

        $residue_text = '';
        $cur_x = 0;
        for ($i = 0; $i < mb_strlen($content,'utf8'); $i++) {
//            $box = imagettfbbox($font_size, 0, $font_file, $p);
//            $p_width = $box[2] - $box[0];

            if($text_align=='left'){
                $text = mb_substr($content, $i, 1,'utf-8');//拆分字符串
                if(!$br && $text_indent){//看看是否要首行缩进,并且只有居左的才要首行缩进
                    $padding_left = $data["padding_left"] + $cn_width*$text_indent;
                    $width = $data["width"] - $cn_width*$text_indent;
                }else{
                    $padding_left = $data["padding_left"];
                    $width = $data["width"];
                }
            }else{
                $text = mb_substr($content, -$i-1, 1,'utf-8');//拆分字符串
                //不是居左就一定居右
                $padding_left = $data["padding_left"] + $data["width"] - $cur_x*2;
                $width = $data["width"];
            }

            $insert_emoji = '';
            if(strlen($text)>3){
                //emoji表情都是4位字节
                $insert_emoji = [
                    'text' => $text,
                    'pos' =>  $padding_left+$cur_x+self::$font_size/4,
                    'pos_y' => $div_height - $line_height
                ];
                $text = ' ';
                $text_position = $cn_width;
            }else if(strlen($text)==3){
                $text_position = $cn_width;
            }else if(strlen($text)==2){
                $text_position = $en_width;
            }else{
                $text_position = imagettfbbox($font_size, 0, $font_file, $text);//用来测量每个字的大小
                $text_position = $text_position[2] - $text_position[0];
            }

            if($maxline){
                //如果已经写入最大行数
                if($rows_total == $maxline){
                    //获取原字符串长度
                    $strlong = mb_strlen($content,'utf8');
                    //抓取剩余字符串
                    $residue_text ='';
                    $residue_text .= mb_substr($content, $i, $strlong - $i,'utf-8');
                    $cc = $strlong - $i;
                    break;
                }
            }
            if ($cur_x + $text_position < $width) {
                if($insert_emoji){
                    $emojis[] = $insert_emoji;
                }
                $p .= $text;
                if ($i == mb_strlen($content,'utf8') - 1) {//判断是否是最后一个字


                    $rows_count++;
                    $rows_total++;
//                    if ($is_write) {//如果传入的参数是false，只做测量，不进行绘制输出
//                        imagettftext($container, $font_size, 0, $padding_left, $div_height, $font_color, $font_file, $p);
//                    }
                    if ($is_write) {//如果传入的参数是false，只做测量，不进行绘制输出
                        imagettftext($container, $font_size, 0, $padding_left+$cur_x, $div_height, $font_color, $font_file, $text);
                    }
                    $div_height += $line_height;
                }else{
                    if ($is_write) {//如果传入的参数是false，只做测量，不进行绘制输出
                        imagettftext($container, $font_size, 0, $padding_left+$cur_x, $div_height, $font_color, $font_file, $text);
                    }
                }
                $cur_x += $cn_width;
            } else {
                $isfuhao = preg_match("/[\\pP]/u", $text) ? true : false;//用来判断最后一个字是不是符号，
                if ($data['symbol_br'] && $isfuhao) {
                    $p .= $text;//如果是符号，我们就不换行，把符号添加到最后一个位置去
                    if ($is_write) {//如果传入的参数是false，只做测量，不进行绘制输出
                        imagettftext($container, $font_size, 0, $padding_left+$cur_x, $div_height, $font_color, $font_file, $text);
                    }
                } else {
                    $i--;//如果不是符号，我们就另起一行，然后这个字再走一遍
                }
                $div_height += $line_height;
                $rows_count++;
                $rows_total++;
//                if($is_write){
//                    imagettftext($container, $font_size, 0, $padding_left, $div_height, $font_color, $font_file, $p);
//                }
                $p = "";//但是不管是不是符号我们都是要另起一行的
                $br = true;//作为是否已换行的标志
                $cur_x = 0;

            }
            if($p==''){
                $a = 1;
            }


        }

        if($is_write) {
            foreach ($emojis as $emoji) {
                $emoji_code = self::emojiToUnicode($emoji['text']);
                $emoji_source = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'] . '/static/emoji/' . $emoji_code . '.png');
                imagecopyresampled($container, $emoji_source, $emoji['pos'], $emoji['pos_y'] + self::$font_size / 1.2, 0, 0, $font_size, $font_size, 60, 60);
            }
        }

        $strdata['tp'] = $rows_count ;//记录当前div有多少行
        $strdata['residueStr'] = $residue_text ;//我们留给下个div有多少个字
        $strdata['wrote_rows'] = $rows_total ;//计算一下所有div一共有多少行
        $strdata['div_height'] = $div_height;//当前div的高度
        return $strdata;
    }


    public static function emojiToUnicode($emoji) {
        // 将 emoji 字符串转换为 Unicode 编码
        $unicode = '';
        $length = mb_strlen($emoji, 'UTF-8'); // 获取 emoji 字符串的长度

        for ($i = 0; $i < $length; $i++) {
            $char = mb_substr($emoji, $i, 1, 'UTF-8');
            $unicode .= strtolower(bin2hex(mb_convert_encoding($char, 'UCS-4', 'UTF-8')));
        }

        $unicode = ltrim($unicode, '0');
        return $unicode;
    }


}